package chapter14.web;

import java.lang.reflect.*;

import chapter14.domain.*;

import com.google.gson.*;

import com.softwarementors.extjs.djn.config.*;
import com.softwarementors.extjs.djn.gson.*;


public class GsonBuilderConfigurator extends DefaultGsonBuilderConfigurator {
    @Override
    public void configure(GsonBuilder builder,
        GlobalConfiguration configuration) {
        super.configure(builder, configuration);
        this.addCustomSerializationSupport(builder);
    }

    protected void addCustomSerializationSupport(GsonBuilder builder) {
        builder.registerTypeAdapter(Menu.class,
            new JsonSerializer<Menu>() {
                public JsonElement serialize(Menu src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = this
                        .convertMenu(src);
                    JsonArray array = new JsonArray();

                    for (Menu child : src.getChildren()) {
                        array.add(this.convertMenu(child));
                    }

                    result.add("children", array);

                    return result;
                }

                protected JsonObject convertMenu(Menu src) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("name", src.getName());
                    result.addProperty("image", src.getImage());
                    result.addProperty("url", src.getUrl());
                    result.addProperty("qtip", src.getQtip());
                    result.addProperty("leaf", src.getChildren().isEmpty());

                    return result;
                }
            });
        builder.registerTypeAdapter(User.class,
            new JsonSerializer<User>() {
                public JsonElement serialize(User src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("name", src.getName());
                    result.addProperty("createDate",
                        src.getCreateDate().getTime());

                    JsonArray array = new JsonArray();

                    for (Role role : src.getRoles()) {
                        JsonObject o = new JsonObject();
                        o.addProperty("id", role.getId());
                        o.addProperty("name", role.getName());
                        array.add(o);
                    }

                    result.add("roles", array);

                    return result;
                }
            });
        builder.registerTypeAdapter(Role.class,
            new JsonSerializer<Role>() {
                public JsonElement serialize(Role src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("name", src.getName());
                    result.addProperty("description", src.getDescription());

                    JsonArray array = new JsonArray();

                    for (Menu menu : src.getMenus()) {
                        JsonObject o = new JsonObject();
                        o.addProperty("id", menu.getId());
                        o.addProperty("name", menu.getName());
                        array.add(o);
                    }

                    result.add("menus", array);

                    return result;
                }
            });
        builder.registerTypeAdapter(Product.class,
            new JsonSerializer<Product>() {
                public JsonElement serialize(Product src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("name", src.getName());
                    result.addProperty("spec", src.getSpec());
                    result.addProperty("price", src.getPrice());

                    return result;
                }
            });
        builder.registerTypeAdapter(In.class,
            new JsonSerializer<In>() {
                public JsonElement serialize(In src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("operator", src.getOperator());
                    result.addProperty("createTime",
                        src.getCreateTime().getTime());
                    result.addProperty("total", src.getTotal());

                    JsonArray ja = new JsonArray();

                    for (InList sub : src.getInLists()) {
                        JsonArray array = new JsonArray();
                        array.add(new JsonPrimitive(sub.getId()));
                        array.add(new JsonPrimitive(sub.getProduct().getId()));
                        array.add(new JsonPrimitive(sub.getName()));
                        array.add(new JsonPrimitive(sub.getQuantity()));
                        array.add(new JsonPrimitive(sub.getPrice()));
                        array.add(new JsonPrimitive(sub.getSubTotal()));
                        ja.add(array);
                    }

                    result.add("subList", ja);

                    return result;
                }
            });
        builder.registerTypeAdapter(Out.class,
            new JsonSerializer<Out>() {
                public JsonElement serialize(Out src, Type typeOrSrc,
                    JsonSerializationContext context) {
                    JsonObject result = new JsonObject();
                    result.addProperty("id", src.getId());
                    result.addProperty("operator", src.getOperator());
                    result.addProperty("createTime",
                        src.getCreateTime().getTime());
                    result.addProperty("total", src.getTotal());

                    JsonArray ja = new JsonArray();

                    for (OutList sub : src.getOutLists()) {
                        JsonArray array = new JsonArray();
                        array.add(new JsonPrimitive(sub.getId()));
                        array.add(new JsonPrimitive(sub.getProduct().getId()));
                        array.add(new JsonPrimitive(sub.getName()));
                        array.add(new JsonPrimitive(sub.getQuantity()));
                        array.add(new JsonPrimitive(sub.getPrice()));
                        array.add(new JsonPrimitive(sub.getSubTotal()));
                        ja.add(array);
                    }

                    result.add("subList", ja);

                    return result;
                }
            });
    }
}
